/* 
 * File:   main.cpp
 * Author: emi
 *
 * Created on 4 de febrero de 2014, 07:03 PM
 */

#include <cstdlib>
#include <limits.h>
#include <string.h>
#include "graph.h"
#include "funciones_grasp.h"
#include "func_generales.h"
#include "grasp.h"
#include "parserNuevo.h"

using namespace std;

void armarInforme(const char* nombreFamilia, Graph* g, int k, int maxIter, int costoCons, int costoBusq1, int costoBusq2) {
    char separador[10];
    strcpy(separador, " ");
    int porcentajeMejora = (costoCons - costoBusq2) * 100 / costoCons;
    cout << "Familia" << separador << "|V|" << separador << "|T|" << separador << "k" << separador << "maxIter" << separador << "c.Cons" << separador << "c.Optimo" << separador << "%Mejora" << endl;
    cout << nombreFamilia << separador << g->sizeG << separador << g->T->size() << separador << k << separador << maxIter << separador << costoCons << separador << costoBusq2 << separador << porcentajeMejora << endl;
};

void grasp(int argc, char** argv) {
    // Parameters Settings ////
    char path_file_in[20];
    strcpy(path_file_in, argv[1]);

    char nombreArchivo[20];
    strcpy(nombreArchivo, argv[2]);

    int diametro = atoi(argv[3]);

    char path_salida[100];
    strcpy(path_salida, argv[4]);

    int k = 20;
    if (argc>5) {
        k = atoi(argv[5]);
    } // an integer more than 1
    int max_iter = 20; // an integer more than 1
    if (argc>6) {
        max_iter = atoi(argv[6]);
    }


    pair<Graph*, PathMatrix*> * G_P;

    Graph * Problem = parserTsp(path_file_in, nombreArchivo);
    Problem->diameter = diametro;

    Graph * G_best = new Graph();
    PathMatrix * PM_G_best = new PathMatrix();

    int G_best_costConst = INT_MAX;
    int G_best_costLocal1 = INT_MAX;
    int G_best_costFinal = INT_MAX;

    int costoConstruccion;
    int costoLocal1;
    int costoLocal2;

    for (int i = 0; i < max_iter; i++) {
        //cout << endl << "Iteracion: " << i + 1 << endl;
        G_P = ConstructGreedyRandomizedSolution(Problem, k);
        if (G_P) { // Si es una solucion factible
RETRY:
            costoConstruccion = G_P->first->Cost();

            LocalSearchKeyPath(Problem, G_P->first, G_P->second);
            costoLocal1 = G_P->first->Cost();
            BusquedaLocal2(Problem, G_P->first, G_P->second);
            costoLocal2 = G_P->first->Cost();
            if (costoLocal2 < G_best_costFinal) {

                delete G_best;
                delete PM_G_best;

                G_best = new Graph(G_P->first);
                //actualizamos los 3 costos
                G_best_costFinal = costoLocal2;
                G_best_costConst = costoConstruccion;
                G_best_costLocal1 = costoLocal1;

                PM_G_best = new PathMatrix(G_P->second);
                //cout << " -- eminabo mejor costo " << G_best_costFinal << ". Y es factible da: " << G_best->esFactible() << endl;
                goto RETRY;
            }
            DeletePair(G_P);
        }
    }
    
    armarInforme(nombreArchivo, G_best, k, max_iter, G_best_costConst, G_best_costLocal1, G_best_costFinal);
    
    Problem->graph_viz(path_salida, nombreArchivo);
    Problem->sub_graph_viz(G_best, path_salida, nombreArchivo);
    imprimirGrafoGLPK(Problem, path_salida, nombreArchivo);

    delete PM_G_best;
    delete G_best;
    delete Problem;

}

/*
 * 
 */
int main(int argc, char** argv) {
    // ./eject path_base nombreArchivo diametro path_salida k maxIter
    if(argc < 4) {
        cout << "Uso: ./dc2nsnp path_base nombreArchivo diametro path_salida [k maxIter]" << endl;
        return -1;
    }

    // initialize random seed
    srand(time(NULL));

    //seed48(time(0));

    grasp(argc, argv);

    return 0;
}

